package com.mayfool.gitmanager.core.helper;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author zhou.xu
 * @description: 日志辅助类
 * 实现了单例模式的日志记录器，支持实时日志更新通知
 * 提供了链式调用API，方便日志的追加和管理
 * 使用观察者模式实现日志变更通知机制
 * @since 2025/3/9 12:03
 */
public class LogHelper {

    /**
     * 日志内容缓冲区
     */
    private final StringBuffer log = new StringBuffer();

    /**
     * 单例实例
     */
    private static final LogHelper logHelper = new LogHelper();

    /**
     * 日志变更监听器列表
     */
    private final List<ChangeListener> listeners = new ArrayList<>();

    private FileWriter writer;
    private SimpleDateFormat dateFormat;

    private LogHelper() {
        try {
            // 创建日志目录
            File logDir = new File("logs");
            if (!logDir.exists()) {
                logDir.mkdirs();
            }

            // 创建日志文件
            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String logFileName = "logs/git-manager-" + dateFormat.format(new Date()) + ".log";
            writer = new FileWriter(logFileName, true);
            
            // 添加JVM关闭钩子，确保文件流正确关闭
            Runtime.getRuntime().addShutdownHook(new Thread(this::close));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取单例实例
     * @return LogHelper实例
     */
    public static LogHelper getInstance() {
        return logHelper;
    }

    /**
     * 追加字符串日志
     * @param msg 日志消息
     * @return 当前实例，支持链式调用
     */
    public LogHelper append(String msg) {
        log.append(msg);
        notifyChange();
        return this;
    }

    /**
     * 追加对象日志
     * 调用对象的toString方法获取日志内容
     * @param msg 日志对象
     * @return 当前实例，支持链式调用
     */
    public LogHelper append(Object msg) {
        log.append(msg);
        notifyChange();
        return this;
    }

    /**
     * 追加字符串日志并换行
     * @param msg 日志消息
     * @return 当前实例，支持链式调用
     */
    public LogHelper appendLine(String msg) {
        log.append(msg).append("\n");
        notifyChange();
        return this;
    }

    /**
     * 追加对象日志并换行
     * 调用对象的toString方法获取日志内容
     * @param msg 日志对象
     * @return 当前实例，支持链式调用
     */
    public LogHelper appendLine(Object msg) {
        log.append(msg).append("\n");
        notifyChange();
        return this;
    }

    /**
     * 获取完整日志内容
     * @return 日志字符串
     */
    public String getLog() {
        return log.toString();
    }

    /**
     * 添加日志变更监听器
     * @param listener 变更监听器
     */
    public void addChangeListener(ChangeListener listener) {
        listeners.add(listener);
    }

    /**
     * 通知所有监听器日志已更新
     * 在每次追加日志后调用
     */
    private void notifyChange() {
        ChangeEvent changeEvent = new ChangeEvent(getInstance());
        listeners.forEach(changeListener -> changeListener.stateChanged(changeEvent));
    }

    /**
     * 记录错误日志
     * 
     * @param message 错误信息
     * @param throwable 异常对象
     */
    public void error(String message, Throwable throwable) {
        try {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timestamp = timeFormat.format(new Date());
            
            // 构建错误日志消息
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append(String.format("[%s] ERROR: %s\n", timestamp, message));
            
            if (throwable != null) {
                errorMsg.append("Exception: ").append(throwable.getMessage()).append("\n");
                for (StackTraceElement element : throwable.getStackTrace()) {
                    errorMsg.append("\tat ").append(element).append("\n");
                }
            }
            
            // 写入文件
            writer.write(errorMsg.toString());
            writer.flush();
            
            // 输出到UI和控制台
            append(errorMsg.toString());
            System.err.print(errorMsg.toString());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 记录错误日志
     * 
     * @param message 错误信息
     */
    public void error(String message) {
        error(message, null);
    }

    /**
     * 记录信息日志
     * 
     * @param message 日志信息
     */
    public void info(String message) {
        try {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timestamp = timeFormat.format(new Date());
            String logMsg = String.format("[%s] INFO: %s\n", timestamp, message);
            
            // 写入文件
            writer.write(logMsg);
            writer.flush();
            
            // 输出到UI和控制台
            append(logMsg);
            System.out.print(logMsg);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 记录警告日志
     * 
     * @param message 警告信息
     */
    public void warn(String message) {
        try {
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timestamp = timeFormat.format(new Date());
            String logMsg = String.format("[%s] WARN: %s\n", timestamp, message);
            
            // 写入文件
            writer.write(logMsg);
            writer.flush();
            
            // 输出到UI和控制台
            append(logMsg);
            System.out.println(logMsg);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭日志写入器
     */
    public void close() {
        try {
            if (writer != null) {
                writer.flush();
                writer.close();
                writer = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
